using System;

using TrueCode.Core.Aspects;
using TrueCode.DependencyManager.BuildActions;
using TrueCode.DependencyManager.BuildActions.Instantiating;

namespace TrueCode.DependencyManager.Extensions.Action.Typed
{
  public static class TypedAcitonExtensions
  {
    public static Container AddDefaultAction< TBuildAction >( [NotNull] this Container container,
                                                              [NotNull] IBuildAction action )
      where TBuildAction : class, IBuildAction
    {
      if( container == null ) throw new ArgumentNullException( "container" );
      container.Actions.AddDefault( typeof( TBuildAction ), action );
      return container;
    }


    public static Container AddActionFor< TAim, TBuildAction >( [NotNull] this Container container,
                                                                [NotNull] TBuildAction action, object settingKey = null )
      where TBuildAction : class, IBuildAction
    {
      if( container == null ) throw new ArgumentNullException( "container" );
      container.Actions.Add( typeof( TBuildAction ), new SessionAim< TAim >( settingKey ), action );
      return container;
    }

    public static Container AddInstantiator< TAim >( [NotNull] this Container container,
                                                     [NotNull] Func< IBuildSession, TAim > factoryMethod )
    {
      if( container == null ) throw new ArgumentNullException( "container" );
      if( factoryMethod == null ) throw new ArgumentNullException( "factoryMethod" );

      container.Actions.Add( typeof( IInstantiate ), new SessionAim< TAim >(),
                             new FactoryMethod< TAim >( factoryMethod ) );
      return container;
    }

    public static Container AddStub< TAim, TBuildAction >( [NotNull] this Container container )
    {
      if( container == null ) throw new ArgumentNullException( "container" );

      container.Actions.Add( typeof( TBuildAction ), new SessionAim< TAim >(), DoNothing.Instance );
      return container;
    }

    public static BuildActionCollection AddDefault< TBuildAction >( [NotNull] this BuildActionCollection actions,
                                                                    [NotNull] IBuildAction action )
      where TBuildAction : class, IBuildAction
    {
      if( actions == null ) throw new ArgumentNullException( "actions" );
      actions.AddDefault( typeof( TBuildAction ), action );
      return actions;
    }


    public static BuildActionCollection AddActionFor< TAim, TBuildAction >(
      [NotNull] this BuildActionCollection actions, [NotNull] TBuildAction action )
      where TBuildAction : class, IBuildAction
    {
      if( actions == null ) throw new ArgumentNullException( "actions" );
      actions.Add( typeof( TBuildAction ), new SessionAim< TAim >(), action );
      return actions;
    }

    public static BuildActionCollection AddActionFor< TAim, TBuildAction >(
      [NotNull] this BuildActionCollection actions, object setting, [NotNull] TBuildAction action )
      where TBuildAction : class, IBuildAction
    {
      if( actions == null ) throw new ArgumentNullException( "actions" );
      actions.Add( typeof( TBuildAction ), new SessionAim< TAim >( setting ), action );
      return actions;
    }
  }
}